package com.cyt.base.redis;

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.List;
import java.util.Set;

@Service
public class RedisService {

    @Autowired(required = false) // 如果运行的Spring容器中有就注入，没有就忽略。
    private JedisPool jedisPool;

    private <T> T execute(Function<T, Jedis> fun) {
        Jedis jedis = null;
        try {
            // 从连接池中获取到jedis分片对象
            jedis = jedisPool.getResource();
            return fun.callback(jedis);
        } finally {
            if (null != jedis) {
                // 关闭，检测连接是否有效，有效则放回到连接池中，无效则重置状态
                jedis.close();
            }
        }
    }

    /**
     * 执行SET操作
     * 
     * @param key
     * @param value
     * @return
     */
    public String set(final String key, final String value) {
        return this.execute(e -> e.set(key, value));
    }

    /**
     * zadd，存储集合，用于从数据库获取list获取
     * @param key
     * @param score
     * @param list
     * @return
     */
    public Long zadd(final String key,final Long score,final List<String> list){
    	return this.execute(e -> {
            for (String value : list) {
                //主要就在这里，但是使用for循环是否使得效率不给力
                return e.zadd(key, score, value);
            }
            //byte[]字节数组，和list集合之间的问题
            //e.zadd(key, score, member);
            return (long) list.size();
        });
    }
    
    /**
     * zadd,根据key存储单个string，需要score得分
     * @param key
     * @param score
     * @param value
     * @return
     */
    public Long zadd(final String key, final Long score, final String value){
    	return this.execute(e -> e.zadd(key, score, value));
    }

    public String hget(final String key, final String field){
        return this.execute(e -> e.hget(key, field));
    }

    public Long hset(final String key, final String field, final String value){
        return this.execute(e -> e.hset(key, field, value));
    }

    public Long sadd(final String key, final String value){
        return this.execute(e -> e.sadd(key, value));
    }

    public Set<String> sinter(final String key){
        return this.execute(e -> e.sinter(key));
    }

    /**
     * 从redis中获取
     * @param key
     * @return
     */
    public Set<String> zrevrange(final String key){
    	return this.execute(e -> e.zrevrange(key, 0, 10));
    }
    
    /**
     * 执行GET操作
     * 
     * @param key
     * @return
     */
    public String get(final String key) {
        return this.execute(e -> e.get(key));
    }

    /**
     * 执行DEL操作
     * 
     * @param key
     * @return
     */
    public Long del(final String key) {
        return this.execute(e -> e.del(key));
    }

    /**
     * 判断是否存在
     */
    public Boolean exists(String key) {
        return this.execute(e -> e.exists(key));
    }

    public Boolean hexists(String key, String field) {
        return this.execute(e -> e.hexists(key, field));
    }

    /**
     * 设置生存时间，单位为：秒
     * 
     * @param key
     * @param seconds
     * @return
     */
    public Long expire(final String key, final Integer seconds) {
        return this.execute(e -> e.expire(key, seconds));
    }

    /**
     * 执行SET操作并且设置生存时间，单位为：秒
     * 
     * @param key
     * @param value
     * @return
     */
    public String set(final String key, final String value, final Integer seconds) {
        return this.execute(e -> {
            String str = e.set(key, value);
            e.expire(key, seconds);
            return str;
        });
    }

    /**
     * 计数,增加
     */
    public Long increment(final String key, final Integer incr){
        return  this.execute(e -> e.incrBy(key,incr));
    }

    /**
     * 计数，正数为增加，负数为减少
     */
    public Long hincrBy(final String key, final String field, final Integer incr){
        return  this.execute(e -> e.hincrBy(key, field, incr));
    }

    /**
     * 计数,减少
     */
    public Long decrBy(final String key, final Integer incr){
        return  this.execute(e -> e.decrBy(key,incr));
    }

    /**
     * 存储REDIS队列 顺序存储,可设置过期时间，过期时间以秒为单位
     */
    public <T> Long rpush(String key, T value, int second) {
        Jedis jedis = null;
        Long ret = null;
        try {
            jedis = jedisPool.getResource();
            // byte[] bytes = BaseUtil.serialize(value);
            String s = JSONObject.toJSONString(value);
            ret = jedis.rpush(key, s);
            if (second > 0) {
                jedis.expire(key, second);
            }
        }  catch (Exception e) {
            e.printStackTrace();
        } finally {
            jedis.close();
        }
        return ret;
    }

    /**
     * 获取存储数据
     */
    public <T> T blpop(String key, int waitSeconds, Class<T> clazz) {
        Jedis jedis = null;
        Long ret = null;
        try {
            jedis = jedisPool.getResource();
            // List<byte[]> values = jedis.brpop(waitSeconds, key.getBytes());
            List<String> values = jedis.brpop(waitSeconds, key);
            if (values != null && values.size() > 0) {
                String value = values.get(1);
                JSONObject json = JSONObject.parseObject(value);
                T t = JSONObject.toJavaObject(json, clazz);
                return t;
            } else {
                return null;
            }
        }  catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            jedis.close();
        }
    }
}
